package com.wd.cloud.applet.utils;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

@Slf4j
public class WeiXinSignUtil {

    /**
     * 请求参数签名
     *
     * @param params 请求参数
     * @return 签名
     */
    public static String sign(Map<String, Object> params, String clientId, String accessToken, String clientRequestUrl, String timestamp, String nonceStr) {
        // log.info("签名参数为：" + params);
        if (params == null) params = new HashMap<>();
        String str = jointParams(sortMapByKey(params), clientId, accessToken, clientRequestUrl, timestamp, nonceStr);
        log.info("待签名字符串为：" + str);
        String sign = MD5(str); //.toUpperCase()
         log.info("签名为：" + sign);
        return sign;
    }

    public static String sign(Map<String, Object> params, String clientId, String accessToken, String clientRequestUrl) {
        return sign(params, clientId, accessToken, clientRequestUrl, null, null);
    }


    /**
     * Map按key ASCII 进行排序
     *
     * @param map 待排序map
     * @return 排序完成的map
     */
    private static Map<String, Object> sortMapByKey(Map<String, Object> map) {
        if (map.isEmpty()) return map;
        Map<String, Object> sortMap = new TreeMap<>(Comparator.naturalOrder());
        sortMap.putAll(map);
        return sortMap;
    }


    /**
     * 把map 拼接成key=value& 格式，并且处理了相关参数
     *
     * @param params
     * @return
     */
    private static String jointParams(Map<String, Object> params, String clientId, String accessToken, String clientRequestUrl, String timestamp, String nonceStr) {
        StringBuilder contrastSign = new StringBuilder();
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String entryKey = entry.getKey();
            Object entryValue = entry.getValue();

            if (entryKey != null && entryValue != null) {
                if (entryValue instanceof Map || entryValue instanceof List) {
                    char[] chs = JSONObject.toJSONString(entryValue, SerializerFeature.WriteMapNullValue).toCharArray();
                    Arrays.sort(chs);
                    entryValue = new String(chs);
                    // throw new CustomException("参数是对象");
                }
                contrastSign
                        .append(entryKey)
                        .append("=")
                        .append(entryValue)
                        .append("&");
            }
        }
        contrastSign.append("url=").append(clientRequestUrl).append("&");

        if (!StringUtils.isEmpty(accessToken)) {
            contrastSign.append("accessToken=").append(accessToken).append("&");
        }
        if (!StringUtils.isEmpty(timestamp)) {
            contrastSign.append("timestamp=").append(timestamp).append("&");
        }

        if (!StringUtils.isEmpty(nonceStr)) {
            contrastSign.append("nonceStr=").append(nonceStr).append("&");
        }
        contrastSign.append("key=").append(clientId);
        return contrastSign.toString();
    }


    public static String MD5(String str) {
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            System.out.println(e.toString());
            return null;
        }
        md.update(str.getBytes());
        //new BigInteger 得到到是一个数字类型，如果前面是0，则会被省略
        str = new BigInteger(1, md.digest()).toString(16);
        //处理前面0不显示问题
        while (str.length() < 32) {
            str = "0" + str;
        }
        return str;
    }
}
